/********************************************************************
	Created:	2011/02/22    12:59 
	Filename: 	Entity.h
	Author:		falconwang
*********************************************************************/

#ifndef Entity_H__
#define Entity_H__

#include "EventSystem/inc/EventTarget.h"

namespace Ent
{
	typedef unsigned int EntID;

	class Component;
	class EntityTemplate;

	enum EntityStatus
	{
		ENT_STATUS_UNLOAD = 0,  // entity is not loaded yet.
		ENT_STATUS_LOADING,     // entity is loading
		ENT_STATUS_NORMAL,      // entity is loaded, and can be updated.
		ENT_STATUS_DESTROY,        // entity is to be delete.
	};

	class Entity : public ES::EventTarget
	{
	public:

		/**
		 * Start to load all res of this entity
		 * */
		void				Load();

		/**
		 * Call Finalize after this entity has been loaded.
		 * */
		void				Finalize();

		/**
		 * Call PreRelease before this entity to be released.
		 * */
		void				PreRelease();
		
		/**
		 * To Release all res of this entity.
		 * */
		void				Release();

		/**
		 * Add a Component to this Entity
		 * */
		void				AddComponent(Component* _comp);

		/**
		 * Remove a Component from this Entity
		 * */
		void				RemoveComponent(Component* _comp);

		/**
		 * Get Component from its family
		 * */
		template	<class T>
		T*					GetComponent(const std::string& _family);

		/**
		 * Get Component from its family
		 * */
		Component*			GetComponent(const std::string& _family);

		/**
		 * Set status of this Entity. Will dispatch Event.
		 * */
		void				SetStatus(EntityStatus _status);

		/**
		 * Get status of this entity
		 * */
		EntityStatus		GetStatus() const { return m_Status; }

		/**
		 * Get Entity ID
		 * */
		EntID				GetID() const { return m_eID; }

		/**
		 * Get Entity Name
		 * */
		const std::string&	GetName() const { return m_Name; }

		/**
		 * Get Entity TemplateName
		 * */
		const std::string&	GetTemplateName() const { return m_TemplateName; }

	private:

		friend class EntityManager;

		/**
		* Create Entity with id and template. Should always created from EntityManager.
		* */
		Entity(EntID _id, const std::string& _entityName, EntityTemplate* _Template);

		/**
		* Destructor. Entity should always be destructed from EntityManager.
		* */
		~Entity();

		// entity is unique
		Entity(const Entity& _other); 

	private:

		std::map<std::string, Component*>	m_Comps;

		EntityStatus						m_Status;

		std::string							m_Name;

		std::string							m_TemplateName;

		EntID								m_eID;
	};

	template	<class T>
	T* Ent::Entity::GetComponent(const std::string& _family)
	{
		return dynamic_cast<T*>(GetComponent(_family));
	}
}

#endif // Entity_H__